package com.copyctrl.campus.portal.controller;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.copyctrl.campus.common.constant.RedisConstant;
import com.copyctrl.campus.common.constant.UtilConstant;
import com.copyctrl.campus.common.model.ApiResponse;
import com.copyctrl.campus.portal.service.UserService;
import com.copyctrl.model.CampUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author:JH
 * @version:1.0
 */
@RestController
@RequestMapping("/authorization")
public class AuthorizationController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/getTokenByCode/{code}")
    public ApiResponse getToken(@PathVariable String code) {
        ApiResponse resp = null;
        //先利用微信官方提供的接口用code换取openid
        String appid = "wxff57c589a713408d";
        String secret = "fbf22bcd7f71e7816dd02672bac14ac7";
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("appid", appid);
        params.add("secret", secret);
        params.add("js_code", code);
        params.add("grant_type", "authorization_code");
        HttpEntity<MultiValueMap<String, String>> request =
                new HttpEntity<MultiValueMap<String, String>>(params, headers);
        String json = restTemplate.postForObject(url, request, String.class);
        Map result = JSONUtil.toBean(json, HashMap.class);
        System.out.println(result);
        String openid = null;
        //在把用户信息加入数据库前先进行查询操作，若数据库无此人在进行操作，如果有直接使用openid
        if (result.containsKey("openid")) {
            String token = UUID.randomUUID().toString(true);
            String name = null;
            openid = result.get("openid").toString();
            //从redis中获取user，如果没有再从数据库中做查询操作
            String userJson = stringRedisTemplate.opsForValue().get(RedisConstant.USER_KEY + openid);
            System.out.println("json:"+userJson);
            if (StrUtil.isBlank(userJson)) {
                CampUser user = userService.findUserByOpenId(openid);
                //从数据库未查到用户
                if (user == null) {
                    user = new CampUser();
                    //新增用户
                    user.setOpenid(openid);
                    user.setCreateTime(new Date());
                    user.setLevel(1);
                    user.setScore(0);
                    String number = RandomUtil.randomNumbers(10);
                    user.setName(UtilConstant.USER_DEFAULT_PREFIX + number);
                    //给用户生成number供好友查找
                    user.setNumber(number);
                    int i = userService.insertUser(user);
                    if (i == 1) {
                        //新增成功，添加到redis中,返回token
                        stringRedisTemplate.opsForValue().set(RedisConstant.USER_KEY + openid, JSONUtil.toJsonStr(user));
                        //把自己加入粉丝列表
                        stringRedisTemplate.opsForSet().add(RedisConstant.USER_IS_FOLLOWED+user.getId(),user.getId().toString());
                        //把自己加入关注列表
                        stringRedisTemplate.opsForSet().add(RedisConstant.USER_FOLLOW+user.getId(),user.getId().toString());
                        //把自己加入好友列表
                        stringRedisTemplate.opsForSet().add(RedisConstant.USER_FRIEND+user.getId(),user.getId().toString());
                        //把id-openid映射加入redis中
                        stringRedisTemplate.opsForHash().put(RedisConstant.ID_OPENID,user.getId().toString(),openid);
                        resp = ApiResponse.ofSuccess(token);
                    } else {
                        //注册失败，不返回token
                        resp = ApiResponse.ofFailure("小程序初始化失败，请联系管理员");
                    }
                }else {
                    //数据库中已有用户，把用户信息更新到redis中，返回token（这种情况一般是服务器端版本更新redis清空）
                    stringRedisTemplate.opsForValue().set(RedisConstant.USER_KEY + openid, JSONUtil.toJsonStr(user));
                    stringRedisTemplate.opsForHash().put(RedisConstant.ID_OPENID,user.getId().toString(),openid);
                    stringRedisTemplate.opsForSet().add(RedisConstant.USER_IS_FOLLOWED+user.getId(),user.getId().toString());
                    //把自己加入关注列表
                    stringRedisTemplate.opsForSet().add(RedisConstant.USER_FOLLOW+user.getId(),user.getId().toString());
                    //把自己加入好友列表
                    stringRedisTemplate.opsForSet().add(RedisConstant.USER_FRIEND+user.getId(),user.getId().toString());
                    resp = ApiResponse.ofSuccess(token);
                }
            }else {
                //从redis中正常查到用户信息，小程序使用code登录有效，换取token给小程序端，正常返回token
                resp = ApiResponse.ofSuccess(token);
            }
            stringRedisTemplate.opsForValue().set(RedisConstant.TOKEN_KEY+token,openid,RedisConstant.LOGIN_USER_TTL, TimeUnit.MINUTES);
        } else {
            resp = ApiResponse.ofFailure("code超时，请重启小程序");
        }
        return resp;
    }
}
